/**
 * 
 */
package org.swing.utility.jdbc.handler;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;

import org.swing.utility.jdbc.imp.RowProcessor;

/**
 * @author lqnhu
 *
 */
public class KeyedHandler extends
		AbstractKeyedHandler<Object, Map<String, Object>> {
	/**
	 * The RowProcessor implementation to use when converting rows into Objects.
	 */
	protected final RowProcessor convert;
	/**
	 * The column index to retrieve key values from. Defaults to 1.
	 */
	protected final int columnIndex;
	/**
	 * The column name to retrieve key values from. Either columnName or
	 * columnIndex will be used but never both.
	 */
	protected final String columnName;

	/**
	 * Creates a new instance of KeyedHandler. The value of the first column of
	 * each row will be a key in the Map.
	 */
	public KeyedHandler() {
		this(ArrayHandler.ROW_PROCESSOR, 1, null);
	}

	/**
	 * Creates a new instance of KeyedHandler. The value of the first column of
	 * each row will be a key in the Map.
	 *
	 * @param convert
	 *            The <code>RowProcessor</code> implementation to use when
	 *            converting rows into Maps
	 */
	public KeyedHandler(RowProcessor convert) {
		this(convert, 1, null);
	}

	/**
	 * Creates a new instance of KeyedHandler.
	 *
	 * @param columnIndex
	 *            The values to use as keys in the Map are retrieved from the
	 *            column at this index.
	 */
	public KeyedHandler(int columnIndex) {
		this(ArrayHandler.ROW_PROCESSOR, columnIndex, null);
	}

	/**
	 * Creates a new instance of KeyedHandler.
	 *
	 * @param columnName
	 *            The values to use as keys in the Map are retrieved from the
	 *            column with this name.
	 */
	public KeyedHandler(String columnName) {
		this(ArrayHandler.ROW_PROCESSOR, 1, columnName);
	}

	/**
	 * Private Helper
	 * 
	 * @param convert
	 *            The <code>RowProcessor</code> implementation to use when
	 *            converting rows into Maps
	 * @param columnIndex
	 *            The values to use as keys in the Map are retrieved from the
	 *            column at this index.
	 * @param columnName
	 *            The values to use as keys in the Map are retrieved from the
	 *            column with this name.
	 */
	private KeyedHandler(RowProcessor convert, int columnIndex,
			String columnName) {
		super();
		this.convert = convert;
		this.columnIndex = columnIndex;
		this.columnName = columnName;
	}

	/**
	 * This factory method is called by <code>handle()</code> to retrieve the
	 * key value from the current <code>ResultSet</code> row. This
	 * implementation returns <code>ResultSet.getObject()</code> for the
	 * configured key column name or index.
	 * 
	 * @param rs
	 *            ResultSet to create a key from
	 * @return Object from the configured key column name/index
	 * @throws SQLException
	 *             if a database access error occurs
	 */
	@Override
	protected Object createKey(ResultSet rs) throws SQLException {
		return (columnName == null) ? rs.getObject(columnIndex) : rs
				.getObject(columnName);
	}

	/**
	 * This factory method is called by <code>handle()</code> to store the
	 * current <code>ResultSet</code> row in some object. This implementation
	 * returns a <code>Map</code> with case insensitive column names as keys.
	 * Calls to <code>map.get("COL")</code> and <code>map.get("col")</code>
	 * return the same value.
	 * 
	 * @param rs
	 *            ResultSet to create a row from
	 * @return Object typed Map containing column names to values
	 * @throws SQLException
	 *             if a database access error occurs
	 */
	@Override
	protected Map<String, Object> createRow(ResultSet rs) throws SQLException {
		return this.convert.toMap(rs);
	}
}
